using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;
using System.Diagnostics.Contracts;
using Konst3d.Efficiency.Suite;

namespace PEM
{
	internal partial class MonitorsViewModel
	{
		#region Commands

		public abstract class BaseCommand : ICommand
		{
			#region Constructor

			public BaseCommand(MonitorsViewModel model)
			{
				Contract.Requires(model != null);
				_model = model;
			}

			#endregion // Constructor

			#region ICommand Implementation

			public event System.EventHandler CanExecuteChanged;

			public abstract bool CanExecute(object parameter);
			public abstract void Execute(object parameter);

			protected void NotifyCanExecuteChanged(EventArgs args = null)
			{
				if (CanExecuteChanged != null)
				{
					CanExecuteChanged(this, args ?? EventArgs.Empty);
				}
			}

			#endregion

			#region Fields

			protected MonitorsViewModel _model;

			#endregion // Fields
		}

		public class AddMonitorCommand : BaseCommand
		{
			#region Constructor

			public AddMonitorCommand(MonitorsViewModel model) :
				base(model)
			{
				_model.SuiteOpened += OnSuiteChange;
				_model.SuiteClosed += OnSuiteChange;
				_model.SuiteCreated += OnSuiteChange;
				_model.SuiteDeleted += OnSuiteChange;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Suite != null;
			}

			public override void Execute(object parameter)
			{
				_model.AddMonitor();
			}

			#endregion

			#region Event Handlers

			private void OnSuiteChange(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		public class RemoveMonitorCommand : BaseCommand
		{
			#region Constructor

			public RemoveMonitorCommand(MonitorsViewModel model) :
				base(model)
			{
				_model.MonitorSelected += OnMonitorSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null;
			}

			public override void Execute(object parameter)
			{
				_model.RemoveMonitor();
			}

			#endregion

			#region Event Handlers

			private void OnMonitorSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		public class EditMonitorCommand : BaseCommand
		{
			#region Constructor

			public EditMonitorCommand(MonitorsViewModel model) :
				base(model)
			{
				_model.MonitorSelected += OnMonitorSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null;
			}

			public override void Execute(object parameter)
			{
				_model.EditMonitor();
			}

			#endregion

			#region Event Handlers

			private void OnMonitorSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		public class ShowStatisticCommand : BaseCommand
		{
			#region Constructor

			public ShowStatisticCommand(MonitorsViewModel model) :
				base(model)
			{
				_model.MonitorSelected += OnMonitorSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null;
			}

			public override void Execute(object parameter)
			{
				_model.ShowStatistic();
			}

			#endregion

			#region Event Handlers

			private void OnMonitorSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		/* shouldn't this be done in XAML via binding?
		public class ChangeMonitorActiveCommand : BaseCommand
		{
			#region Constructor

			public ChangeMonitorActiveCommand(MonitorsViewModel model) :
				base(model)
			{
				// _model.MonitorSelected += OnMonitorSelected;
				// _model.SelectedTaskStateChanged += OnTaskSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null && _model.Selected.State != (TaskState)parameter;
			}

			public override void Execute(object parameter)
			{
				_model.ChangeTaskState((TaskState)parameter);
			}

			#endregion

			#region Event Handlers

			private void OnTaskSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}
		*/

		#endregion // Commands

		#region Commands Collection

		public class CommandsCollection
		{
			#region Properties

			public AddMonitorCommand AddMonitor
			{
				get;
				private set;
			}

			public RemoveMonitorCommand RemoveMonitor
			{
				get;
				private set;
			}

			public EditMonitorCommand EditMonitor
			{
				get;
				private set;
			}

			public ShowStatisticCommand ShowStatistic
			{
				get;
				private set;
			}

			#endregion // Properties

			#region Constructor

			public CommandsCollection(MonitorsViewModel host)
			{
				Contract.Requires(host != null);

				AddMonitor = new AddMonitorCommand(host);
				RemoveMonitor = new RemoveMonitorCommand(host);
				EditMonitor = new EditMonitorCommand(host);
				ShowStatistic = new ShowStatisticCommand(host);
			}

			#endregion // Constructor
		}

		#endregion // Commands Collection

		public void AddMonitor()
		{
			Contract.Requires(Suite != null);

			if (_createEditMonitorDlg.ShowDialog(_parentWindow))
			{
				int id = Suite.Monitors.Add(MonitorType.Monitor, _createEditMonitorDlg.MonitorTitle, _createEditMonitorDlg.MonitorDescription, DateTime.Now, true);

				var monitor = Suite.Monitors[id];
				var activeDays = _createEditMonitorDlg.GetActiveWeekDays();

				for (int i = 0; i < 7; ++i)
				{
					monitor.ActiveDays.DaysOfWeek[i] = activeDays[i];
				}

				UpdateMonitorList();
			}

		}

		public void RemoveMonitor()
		{
			Contract.Requires(Suite != null);
			Contract.Requires(Selected != null);

			if (MessageBox.Show(_parentWindow, "Are you sure, you wish to delete this monitor?", "Delete monitor?", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
			{
				Suite.Monitors.Remove(Selected.ID);
				UpdateMonitorList();
			}
		}

		public void EditMonitor()
		{
			Contract.Requires(Suite != null);
			Contract.Requires(Selected != null);

			if (_createEditMonitorDlg.ShowDialog(_parentWindow, Selected))
			{
				Selected.Title = _createEditMonitorDlg.MonitorTitle;
				Selected.Description = _createEditMonitorDlg.MonitorDescription;

				var activeDays = _createEditMonitorDlg.GetActiveWeekDays();

				for (int i = 0; i < 7; ++i)
				{
					Selected.ActiveDays.DaysOfWeek[i] = activeDays[i];
				}

				Monitors.NotifyItemChanged(Selected);
			}
		}

		public void ShowStatistic()
		{
			Contract.Requires(Suite != null);
			Contract.Requires(Selected != null);

			_statisticDialog.ShowDialog(_parentWindow, Selected);
		}

		/* shouldn't this be done in XAML via binding?
		public void SetMonitorActive(IMonitor monitor, bool active)
		{
			//
		}
		*/

		// show details
	}
}
